#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/time.h>
#include"simple_queue.h"
 
pthread_cond_t msg_cond = PTHREAD_COND_INITIALIZER;
pthread_cond_t msg_cond2 = PTHREAD_COND_INITIALIZER;
 
simple_queue* create_simple_queue(int queue_length)
{
	simple_queue *this = NULL;
	
	this = (simple_queue*)malloc(sizeof(simple_queue) + queue_length * sizeof(void*));
	if (NULL != this)
	{
		this->front = 0;
		this->rear = 0;
		this->length = queue_length;
		if (0 != pthread_mutex_init(&(this->data_mutex), NULL))
		{
				printf("[%s]pthread_mutex_init failed!\n", __FUNCTION__);
				free(this);
				this = NULL;
				return NULL;
		}
	}
	else
	{
		printf("[%s]malloc is failed!\n", __FUNCTION__);
		return NULL;
	}
	
	return this;
}
 
/*
*/
queue_status is_full_queue(simple_queue* p_queue)
{
	queue_status ret = QUEUE_IS_NORMAL;
	
	do
	{
		if (NULL == p_queue)
		{
			printf("[%s] param is error\n", __FUNCTION__);
			ret = QUEUE_NO_EXIST;
			break;
		}
		if (p_queue->front == ((p_queue->rear + 1) % (p_queue->length)))
		{
			printf("[%s] queue is full\n", __FUNCTION__);
			ret = QUEUE_IS_FULL;
			break;
		}
	}while(0);
	
	return ret;
}
 
/*
*/
queue_status is_empty_queue(simple_queue* p_queue)
{
	queue_status ret = QUEUE_IS_NORMAL;
	
	do
	{
		if (NULL == p_queue)
		{
			printf("[%s] param is error\n", __FUNCTION__);
			ret = QUEUE_NO_EXIST;;
			break;
		}
		if (p_queue->front == p_queue->rear)
		{
			printf("[%s] queue is empty\n", __FUNCTION__);
			ret = QUEUE_IS_EMPTY;
			break;
		}
	}while(0);
	
	return ret;
}
/*
*/
cntl_queue_ret push_simple_queue(simple_queue* p_queue, void* data)
{
	int w_cursor = 0;
	
	if(NULL == p_queue || NULL == data)
	{
		printf("[%s] param is error\n", __FUNCTION__);
		return CNTL_QUEUE_PARAM_ERROR;
	}
	
	pthread_mutex_lock(&(p_queue->data_mutex));
 
	w_cursor = (p_queue->rear + 1)%p_queue->length;
	while (w_cursor == p_queue->front)
	{
        pthread_cond_wait(&msg_cond2, &(p_queue->data_mutex));
		w_cursor = (p_queue->rear + 1)%p_queue->length;
	}
	p_queue->data[p_queue->rear] = data;
	p_queue->rear = w_cursor;
 
	pthread_mutex_unlock(&(p_queue->data_mutex));
	// pthread_cond_signal(&msg_cond);
	pthread_cond_broadcast(&msg_cond);
	
	return CNTL_QUEUE_SUCCESS;
}
 
/*
*/
cntl_queue_ret pop_simple_queue(simple_queue* p_queue, void** data)
{
	if(NULL == p_queue)
	{
		printf("[%s] param is error\n", __FUNCTION__);
		return CNTL_QUEUE_PARAM_ERROR;
	}
 
	pthread_mutex_lock(&(p_queue->data_mutex));
	if (p_queue->front == p_queue->rear)
	{
		pthread_cond_wait(&msg_cond, &(p_queue->data_mutex));
	}
	*data = p_queue->data[p_queue->front];
	p_queue->front = (p_queue->front + 1)%p_queue->length;
	
	pthread_mutex_unlock(&(p_queue->data_mutex));
	// pthread_cond_signal(&msg_cond);
	pthread_cond_broadcast(&msg_cond2);
	
	return CNTL_QUEUE_SUCCESS;
}
cntl_queue_ret destroy_simple_queue(simple_queue* p_queue)
{
	cntl_queue_ret ret = CNTL_QUEUE_SUCCESS;
	
	if(NULL == p_queue)
	{
		printf("[%s] param is error\n", __FUNCTION__);
		ret = CNTL_QUEUE_PARAM_ERROR;
	}
	else
	{
		pthread_mutex_destroy(&(p_queue->data_mutex));
		pthread_cond_destroy(&msg_cond);
		while (p_queue->front != p_queue->rear)//删除队列中残留的消息
		{
			free(p_queue->data[p_queue->front]);
			p_queue->front = (p_queue->front + 1)%p_queue->length;
		}
		free(p_queue);
		p_queue = NULL;
	}
	
	return ret;
}